package utils

import (
	"database/sql/driver"
	"encoding/json"
	"fmt"
	"woo-server/coms/consts"
	"time"
)

// CustomTime 自定义时间类型
type CustomTime time.Time

// Scan sql.Scanner implementation to convert a time.Time column to a LocalDate
func (ct *CustomTime) Scan(value interface{}) error {
	if tm, ok := value.(time.Time); ok {
		*ct = CustomTime(tm)
		return nil
	}
	return fmt.Errorf("invalid time.Time format")
}

// Value sql/driver.Valuer implementation to go from LocalDate -> time.Time
func (ct CustomTime) Value() (driver.Value, error) {
	if time.Time(ct).IsZero() {
		return nil, nil
	}
	return time.Time(ct).Format(consts.TimeFormat), nil
}

// MarshalJSON CustomTime 序列化方法
func (ct *CustomTime) MarshalJSON() ([]byte, error) {
	if time.Time(*ct).IsZero() {
		return []byte("null"), nil
	}
	return json.Marshal(time.Time(*ct).Format(consts.TimeFormat))
}

// UnmarshalJSON CustomTime反序列化方法，支持yyyy-MM-dd 和 yyyy-MM-dd hh:mm:ss 格式 "0001-01-01"
func (ct *CustomTime) UnmarshalJSON(j []byte) error {
	// 首选反序列化为字符串，再从字符串转换为Time类型
	var timeStr string
	if err := json.Unmarshal(j, &timeStr); err != nil {
		return err
	}

	if len(timeStr) == 0 {
		// 为空的情况
		*ct = CustomTime(time.Time{})
		return nil
	}

	if len(timeStr) == 10 {
		// 把yyyy-MM-dd 补齐到 yyyy-MM-dd hh:mm:ss
		timeStr += " 00:00:00"
	}
	date, err := time.ParseInLocation(consts.TimeFormat, timeStr, time.Local)
	if err != nil {
		date, err = time.ParseInLocation(consts.TimeFormatWithT, timeStr, time.Local)
		if err != nil {
			return err
		}
	}
	*ct = CustomTime(date)
	return nil
}

// FromCustomTime 获取时间
func FromCustomTime(ct CustomTime) *time.Time {
	t := time.Time(ct)
	if t.IsZero() {
		return nil
	}
	return &t
}

// TimeSubDays 计算两个日期相差天数
func TimeSubDays(t1, t2 time.Time) int {

	if t1.Location().String() != t2.Location().String() {
		return -1
	}
	hours := t1.Sub(t2).Hours()

	if hours <= 0 {
		return -1
	}
	// sub hours less than 24
	if hours < 24 {
		// may same day
		t1y, t1m, t1d := t1.Date()
		t2y, t2m, t2d := t2.Date()
		isSameDay := (t1y == t2y && t1m == t2m && t1d == t2d)

		if isSameDay {

			return 0
		} else {
			return 1
		}

	} else { // equal or more than 24

		if (hours/24)-float64(int(hours/24)) == 0 { // just 24's times
			return int(hours / 24)
		}
		return int(hours/24) + 1

	}

}
